﻿// 
// SpeedReader is a program that allows you to learn speed reading.
// Copyright (C) 2010 Wiesław Šoltés
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Threading;
using System.Windows.Threading;
using System.IO;

namespace SpeedReader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private DispatcherTimer timer;
        private MatchCollection wordCollection;
        private int currentWord = 0;
        private int wordCount = 0;
        private bool haveCollection = false;

        public int getWords(string s, int c)
        {
            //wordCollection = Regex.Matches(s, @"[\S]+");
            wordCollection = Regex.Matches(s, @"((?:(\S+\s+){0," + (c-1).ToString()  + @"})\S+)");
            //foreach (Match match in wordCollection) Debug.Print(match.Value);

            return wordCollection.Count;
        }

        public MainWindow()
        {
            InitializeComponent();

            this.Title = "SpeedReader";

            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);

            buttonLoadRtf.Click += new RoutedEventHandler(buttonLoadRtf_Click);
            buttonSaveRtf.Click += new RoutedEventHandler(buttonSaveRtf_Click);

            buttonPlayPause.Click += new RoutedEventHandler(buttonPlayPause_Click);
            buttonParseReset.Click += new RoutedEventHandler(buttonParseReset_Click);
            sliderWords.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliderWords_ValueChanged);
        }

        void buttonSaveRtf_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog fd = new Microsoft.Win32.SaveFileDialog();
            fd.Filter = "RTF Document (*.rtf)|*.rtf";
            fd.FilterIndex = 0;
            fd.FileName = "Document";
            if (fd.ShowDialog() == true)
            {
                SaveRtfDocument(fd.FileName);
            }
        }

        void buttonLoadRtf_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
            fd.Filter = "RTF Document (*.rtf)|*.rtf|All Files (*.*)|*.*";
            fd.FilterIndex = 0;
            fd.FileName = "";
            if (fd.ShowDialog() == true)
            {
                LoadRtfDocument(fd.FileName);
            }
        }

        void sliderWords_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (haveCollection)
            {
                currentWord = (int)sliderWords.Value;
                words.Text = wordCollection[currentWord].Value;
            }
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            sliderWords.Minimum = 0;
            sliderWords.Maximum = 0;
            sliderWords.Value = 0;

            timer = new DispatcherTimer();
            timer.Tick += timer_Tick;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (haveCollection)
            {
                if (currentWord < wordCount)
                {
                    //words.Text = wordCollection[currentWord].Value;
                    sliderWords.Value = currentWord;
                    currentWord++;
                }
                else
                {
                    timer.Stop();
                }
            }
        }

        void LoadRtfDocument(string fileName)
        {
            if(System.IO.File.Exists(fileName))
            {
                try
                {
                    System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                    using (fs)
                    {
                        TextRange tr = new TextRange(text.Document.ContentStart, text.Document.ContentEnd);
                        tr.Load(fs, DataFormats.Rtf);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        void SaveRtfDocument(string fileName)
        {
            try
            {
                System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
                using (fs)
                {
                    TextRange tr = new TextRange(text.Document.ContentStart, text.Document.ContentEnd);
                    tr.Save(fs, DataFormats.Rtf);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        void buttonParseReset_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (haveCollection)
                {
                    wordCount = 0;

                    wordCounter.Text = "";

                    sliderWords.Minimum = 0;
                    sliderWords.Maximum = 0;
                    sliderWords.Value = 0;
                    currentWord = 0;

                    text.Visibility = System.Windows.Visibility.Visible;
                    words.Visibility = System.Windows.Visibility.Hidden;

                    words.Text = "";

                    haveCollection = false;
                }
                else
                {
                    string myText = new TextRange(text.Document.ContentStart, text.Document.ContentEnd).Text;
                    int wordChunks = int.Parse(chunks.Text);

                    wordCount = getWords(myText, wordChunks);

                    wordCounter.Text = wordCount.ToString();

                    sliderWords.Minimum = 0;
                    sliderWords.Maximum = wordCount - 1;
                    sliderWords.Value = 0;
                    currentWord = 0;

                    text.Visibility = System.Windows.Visibility.Hidden;
                    words.Visibility = System.Windows.Visibility.Visible;

                    haveCollection = true;

                    words.Text = wordCollection[currentWord].Value; ;
                    sliderWords.Value = 0;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        void buttonPlayPause_Click(object sender, RoutedEventArgs e)
        {
            if (haveCollection)
            {
                if (timer.IsEnabled)
                    Pause();
                else
                    Play();
            }
        }

        void Play()
        {
            double wpmValue = double.Parse(wpm.Text);
            if (wpmValue > 0)
            {
                double delay = (1000.0 / (wpmValue / 60.0)) * int.Parse(chunks.Text);
                //Debug.Print(delay.ToString());

                timer.Interval = TimeSpan.FromMilliseconds(delay);
                timer.Start();
            }
            else
            {
                MessageBox.Show("wpm must be greater than 0", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        void Pause()
        {
            timer.Stop();
        }
    }
}
